<?


JCAT_Package::ImportClass('JCAT_ArchiveDocument',JCAT::PACKAGE_DOC) ;

abstract class CoderDocBase extends JCAT_ArchiveDocument implements IToolboxCoderDocument
{

	/**
	 * What's this Method ?
	 * 
	 * @access	public
	 * @param	$sName=''	string	What's this Parameter ?
	 * @param	$sPath=''	string	What's this Parameter ?
	 * @return	void
	 */
	public function CoderDocBase( $sName='', $sPath='' ) 
	{
		$this->JCAT_ArchiveDocument($sName,$sPath) ;
		$this->SetByteLenPerLine(240) ;
	}

	
	/**
	 * 从文件中读取内容
	 * 
	 * @access	protected
	 * @param	$sPath		string		what's this
	 * @return	string
	 */
	protected function LoadFromFile( $sPath )
	{
		return $this->ReadUnmodifiableBlock($sPath,self::DATABLOCK_NAME) ;
	}
	
	
	/**
	 * 将序列化以后的内容存入到 文档
	 * 
	 * @access	protected
	 * @param	$sPath				文件路径
	 * @param	$sByteContents		字节内容
	 * @param	$bAsBinary			作为二进制存储
	 * @return	bool
	 */
	protected function SaveToFile( $sPath, $sByteContents, $bAsBinary=false )
	{
		self::WirteUnmodifiableBlock($sPath,self::DATABLOCK_NAME,$sByteContents,self::UnmodifiableBlockKind_Data,0,$this->GetByteLenPerLine()) ;
		return true ;
	}


	/**
	 * what's this
	 * 
	 * @access	public
	 * @return	void
	 */
	static public function WirteUnmodifiableBlock( $sPath, $sBlockName, $sContents, $nKind=self::UnmodifiableBlockKind_Data, $nTab=0, $bBlockLineLength=240 )
	{
		// 打开文件
		JCAT_ASSERT::ASSERT_FILE($sPath);
		$sSourceContents = file_get_contents($sPath) ;
		
		// 查找 正则式
		$sRegexp = self::GetUnmodifiableBlockRegexp($sBlockName) ;
		
		// 产生内容
		$sNewContents = '' ;
		
		// 已经存在, 可替换
		if( preg_match($sRegexp,$sSourceContents) )
		{
			$sNewBlock = self::MakeUnmodifiableBlock($sBlockName,&$sContents,$nKind==self::UnmodifiableBlockKind_Code,$bBlockLineLength,$nTab,false) ;
			$sNewContents = preg_replace($sRegexp,$sNewBlock,$sSourceContents) ;
		}
		
		// 追加
		else
		{
			if( $nKind==self::UnmodifiableBlockKind_Data )
			{
				$sNewBlock = self::MakeUnmodifiableBlock($sBlockName,&$sContents,$nKind==self::UnmodifiableBlockKind_Code,$bBlockLineLength,$nTab,true) ;
				$sNewContents = $sSourceContents.="<?\r\n{$sNewBlock}\r\n?>" ;
			}
			else
			{
				$sNewContents =& $sSourceContents ;
				// throw new JCAT_Exception(JCAT_Language::SentenceEx('无法定位代码文件中的对话框数据，可能该文件中保存的数据已被损坏。','Toolbox',null),__macro_exception_code__) ;
			}
		}

		// 写入文件
		file_put_contents($sPath,$sNewContents) ;
	}

	/**
	 * what's this
	 * 
	 * @access	public
	 * @return	array
	 */
	static public function ReadUnmodifiableBlock($sPath, $sBlockName)
	{
		// 打开文件
		JCAT_ASSERT::ASSERT_FILE($sPath);
		$sSourceContents = file_get_contents($sPath) ;
		
		// 查找 正则式
		$sRegexp = self::GetUnmodifiableBlockRegexp($sBlockName) ;
		
		// 查找 ... ...
		if( preg_match($sRegexp,$sSourceContents,$arrRes) )
		{
			JCAT_ASSERT::ASSERT_( isset($arrRes[self::REGEXP_UNMODIFIABLE_BLOCK_CONTENT_GROUP]), 'regexp is wrong!!!!' ) ;
			$sData = $arrRes[self::REGEXP_UNMODIFIABLE_BLOCK_CONTENT_GROUP] ;
			
			// 返回			
			return trim($sData) ;
		}
		else
			throw new JCAT_Exception(JCAT_Language::SentenceEx('无法定位代码文件中的对话框数据，可能该文件中保存的数据已被损坏。','Toolbox',null),__macro_exception_code__) ;
	}
	
	
	/**
	 * what's this
	 * 
	 * @access	protected
	 * @static 
	 * @return	string
	 */
	static protected function GetUnmodifiableBlockRegexp( $sBlockName )
	{
		// 查找 正则式
		$sBlockName = str_replace(' ','\s',$sBlockName) ;
		$sBlockName = str_replace('.','\\.',$sBlockName) ;
		return sprintf(self::REGEXP_UNMODIFIABLE_BLOCK_PATTERN,$sBlockName,$sBlockName) ;
	}

	
	/**
	 * what's this
	 * 
	 * @access	public
	 * @static 
	 * @return	array
	 */
	static public function MakeUnmodifiableBlock( $sBlockName, $sContents, $bIsCode, $nLineLen, $nTab, $bWithWarning )
	{
		// 确定 注释风格
		if($bIsCode)
		{
			$sStartCommentHead = '//' ;
			$sStartCommentFoot = '//' ;
			$sEndCommentHead = '//' ;
			$sEndCommentFoot = '//' ;
		}
		else
		{
			$sStartCommentHead = '/*' ;
			$sStartCommentFoot = '//' ;
			$sEndCommentHead = '//' ;
			$sEndCommentFoot = '*/' ;
		}
		
		// 首尾 标签
		$sStartTag = "<<[UnmodifiableBlock.Start]::{$sBlockName}::>>" ;
		$sEndTag = "<<[UnmodifiableBlock.End]::{$sBlockName}::>>" ;
		
		
		// 格式化 首尾 标签
		if($bIsCode)
		{
			$sStartLineFill = '' ;
			$sEndLineFill = '' ;

			$sTabs = str_repeat("\t",$nTab) ;
		}
		
		else
		{
			$nStartLineFillNum = $nLineLen - strlen($sStartTag) - strlen($sStartCommentHead) - strlen($sStartCommentFoot) ;
			$sStartLineFill = str_repeat('&',$nStartLineFillNum) ;
			
			$nEndLineFillNum = $nLineLen - strlen($sEndTag) - strlen($sEndCommentHead) - strlen($sEndCommentFoot) ;
			$sEndLineFill = str_repeat('&',$nEndLineFillNum) ;
			
			$sTabs = '' ;
		}
		
		
		// 警告内容
		$sWithWarning = (!$bWithWarning)? 
								'' :
								JCAT_Language::SentenceEx("/**\r\n * [注意!!]\r\n *	以下内容由 JCAT PHP Toolbox 自动维护，手动更改的内容会被 JCAT PHP Toolbox 抹除，\r\n *	同时还可能破坏格式，导致 JCAT PHP Toolbox 无法正常读取。\r\n */\r\n",'Toolbox',null) ;

		// 组装内容
		return	$sWithWarning
				. "{$sStartCommentHead}{$sStartTag}{$sStartLineFill}{$sStartCommentFoot}" 
				. "\r\n"
				. $sContents
				. "\r\n"
				. "{$sTabs}{$sEndCommentHead}{$sEndLineFill}{$sEndTag}{$sEndCommentFoot}";
	}
	
	
	/**
	 * what's this
	 * 
	 * @access	public
	 * @return	string
	 */
	public function PrintDeclare()
	{
		return "/**
 * ... ...
 * ... ...
 *
 */" ;
	}
	
	
	
	/**
	 * what's this
	 * 
	 * @access	public
	 * @param	$sDocPath	string			what's this
	 * @param 	static
	 * @return	void
	 */
	static public function WakeupDocument( $sDocPath )
	{
		if(!is_file($sDocPath))
		{
			return null ;
		}
		
		$sPath = JCAT_Global::TidyPath($sDocPath) ;

		// 直接 返回已存在的全局变量
		if( isset(self::$arrCodeDocument[$sPath]) )
		{
			return self::$arrCodeDocument[$sPath] ;
		}
		
		// 读取 UICtrl 的文档数据
		$sByte = CoderDocBase::ReadUnmodifiableBlock($sPath,'Coder Dialog Data') ;
		$sClassName = JCAT_ArchiveDocument::ExtractDocumentClassInSerializeData($sByte) ;

		// 检查 合法性
		if( !JCAT_Global::IsKindOf($sClassName,'CoderDocBase') )
		{
			//JCAT_Gtk::MsgDlg(JCAT_Language::Sentence('文件必须是由 JeCat PHP Toolbox 创建的 UI控件。')) ;
			return null ;
		}

		// 恢复文档
		$aDoc = new $sClassName() ;
		try
		{
			if( !$aDoc->UnserializeData($sByte) )
			{
				return null ;
			}
			
			$aDoc->SetPath($sPath) ;
		}
		catch(Exception $aException )
		{
			return null ;
		}
		
		// 作为全局对象保存
		self::$arrCodeDocument[$sPath] = $aDoc ;
		
		return $aDoc ;
	}
	
	// 属性 //////////////////////////////////////////////
	
	const REGEXP_UNMODIFIABLE_BLOCK_PATTERN = "|#
/[\*/]#													开始注释
<<\[UnmodifiableBlock\.Start\]::%s::>>#					开始标签
&*#														行 填充符 &
[\*/]/#													结束注释
#
\r\n#											
(.+?)#													内容	
\r\n#
#
[\*/]/#													开始注释
&*?#													行 填充符 &
<<\[UnmodifiableBlock\.End\]::%s::>>#					开始标签
[\*/]/#													结束注释
|sx" ;
	
	const REGEXP_UNMODIFIABLE_BLOCK_CONTENT_GROUP = 1 ;
	
	const DATABLOCK_NAME = 'Coder Dialog Data' ;
	
	
	const UnmodifiableBlockKind_Code = 1 ;
	const UnmodifiableBlockKind_Data = 2 ;
	
	
	static private $arrCodeDocument = array() ;
}

?>